import random
import math
from typing import List, Any
import matplotlib.pyplot as plt
import daily_diagnosis_neighbor as neighbor
import copy

import numpy
import pandas as pd

# from COVID import MysqlConnect



'''
    说明：
    （1）在该模型中个体状态的标志有：-1空位，0易感, 1潜伏, 2无症状, 3有症状, 4恢复, 5死亡
    （2）隔离状态的标志分别表示为：-1空位, 0未隔离, 1隔离, 2确诊  , 3死亡
    

'''

class city:


    def __init__(self, N, day, Frequency):

        # self.rate_3_to_5 = None
        self.N = N
        self.day = day  # 天数
        self.Frequency = Frequency  # 输入每天更新个体状态的频率
        # self.infection_Diff = infection_Diff
        # 时间属性
        self.date = 0  # 记录当前的次数
        # 个体属性
        self.person = numpy.zeros(self.N)
        self.isolation_state = numpy.zeros(self.N)
        self.virus_Latency_duration = numpy.zeros(self.N)      # 记录成为潜伏者时长
        self.person_Fixed_latent_period = numpy.zeros(self.N)  # 设置需要潜伏长
        self.isolation_duration = numpy.zeros(self.N)     # 记录当前隔离时长
        self.treatment_time = numpy.zeros(self.N)         # 记录治疗时长
        self.recovery_time = numpy.zeros(self.N)          # 设置治疗时长
        self.asymptomatic_time = numpy.zeros(self.N)      # 记录成为无症状患者时长
        self.asymptomatic_fix_time = numpy.zeros(self.N)  # 设置无症个体状转变时长
        self.symptomatic_time = numpy.zeros(self.N)         # 记录成为感染者的时长
        self.symptomatic_fix_time = numpy.zeros(self.N)     # 设置感染者转变时长
        self.contact_effective_countdown = numpy.zeros(self.N)  # 记录标有效志天数
        self.cloning_person = numpy.zeros(self.N)               # 克隆前一天的个体状态
        self.cloning_isolation_state = numpy.zeros(self.N)      # 克隆前一天的隔离确诊状态
        self.cloning_treatment_time = numpy.zeros(self.N)       # 克隆前一天的治疗时长
        self.throw_num = []  # 投放的潜伏者
        # 一些参数
        # self.r = 0.5
        # self.P1 = 0.1
        # self.P2 = 0.2
        # self.delta = 0
        # self.delta2 = 0.5
        # self.delta1 = 0.2
        # self.b = self.delta
        # self.beta = 0.871
        # self.theta = 0.1703
        # self.theta2 = 0.5
        # self.gt = 14
        # self.migrate_asymptomatic_rate = 0.01  # 迁入无症状感染率
        # self.migrate_infected_rate = 0.02
        # self.migrate_hide_rate = 0.01  # 迁入潜伏率
        # self.detection_accuracy = 0.9
        # self.detections_data = [1, 7, 14]
        # self.discovery_rate_1 = 0.0  # 一层查找通过寻找到密切接触者的概率0.5114
        # self.discovery_rate_2 = 0.0
        # self.cure_rate = 0.9
        # self.death_rate = 0.1
        # self.throw_number = 3
        # self.contact_effective_time # 有效接触时间
        self.un_isolation_judge = []
        self.isolation_person_state = []
        self.isolation_people = []
        self.record_neighbor_state = []

    ''' 
        函数功能：从文件获取所有参数
        
    '''

    def get_parameter_txt(self):
        parameter_file_1 = pd.read_table('input_file\parameter_file_1.txt', sep=":", header=None)
        parameter_file_2 = pd.read_table('input_file\parameter_file_2.txt', sep="\t", header=None)


        self.r = parameter_file_1[1][0]
        self.P1 = parameter_file_1[1][1]
        self.P2 = parameter_file_1[1][2]
        self.delta1 = parameter_file_1[1][3]
        self.delta2 = parameter_file_1[1][4]
        self.b = parameter_file_1[1][5]
        self.beta = parameter_file_1[1][6]
        self.theta = parameter_file_1[1][7]
        self.theta2 = parameter_file_1[1][8]
        self.gt = parameter_file_1[1][9]
        self.maigratin_asymptomatic_rate = parameter_file_1[1][10]  # 迁入无症状感染率
        self.maigratin_infected_rate = parameter_file_1[1][11]
        self.maigratin_hide_rate = parameter_file_1[1][12]  # 迁入潜伏率
        self.detection_accuracy = parameter_file_1[1][13]
        self.discovery_rate_1 = parameter_file_1[1][14]  # parameter_file_1[1][14]  # 一层查找通过寻找到密切接触者的概率
        self.discovery_rate_2 = parameter_file_1[1][15]
        self.cure_rate = parameter_file_1[1][16]
        self.death_rate = parameter_file_1[1][17]
        self.throw_number = parameter_file_1[1][18]
        self.rate_1_to_2 = parameter_file_1[1][19]  # 潜伏者变化为无症状的概率
        self.rate_1_to_3 = parameter_file_1[1][20]
        self.rate_1_to_4 = parameter_file_1[1][21]  # 潜伏者变化为恢复者概率
        self.rate_2_to_3 = parameter_file_1[1][22]  # 无症状变成感染者
        self.rate_2_to_4 = parameter_file_1[1][23]  # 无症状变成恢复者
        self.rate_3_to_5 = parameter_file_1[1][24]
        self.contact_effective_time = parameter_file_1[1][25]  # 有效接触时间

        self.detections_data = [parameter_file_2[2][0], parameter_file_2[2][1], parameter_file_2[2][2]]

        # self.delta = MysqlConnect.delta
        # self.person_Fixed_latentperiod = parameter_file_1[1][9]  # 预计潜伏时长
        # self.throw_number = MysqlConnect.throw_number
        # self.N = 300
        # self.date = 0

    '''
        函数功能：链接数据库
    '''
    # def get_parameter(self):
    #     self.r = 0.5
    #     self.delta = MysqlConnect.delta
    #     self.delta1 = MysqlConnect.delta1
    #     self.delta2 = MysqlConnect.delta2
    #     self.beta = MysqlConnect.beta
    #     self.theta = MysqlConnect.theta
    #     self.theta2 = MysqlConnect.theta2
    #     self.P1 = MysqlConnect.P1
    #     self.P2 = MysqlConnect.P2
    #     self.gt = MysqlConnect.gt
    #     self.maigratin_asymptomatic_rate = MysqlConnect.maigratin_asymptomatic_rate  # 迁入无症状感染率
    #     self.maigratin_infected_rate = MysqlConnect.maigratin_infected_rate
    #     self.maigratin_hide_rate = MysqlConnect.maigratin_hide_rate  # 迁入潜伏率
    #     self.person_Fixed_latentperiod = MysqlConnect.person_Fixed_latentperiod  # 预计潜伏时长
    #     self.detection_accuracy = MysqlConnect.detection_accuracy
    #     self.detections_data = [MysqlConnect.detections_data_day1, MysqlConnect.detections_data_day2,
    #                             MysqlConnect.detections_data_day3]
    #     self.discovery_rate_1 = MysqlConnect.discovery_rate_1  # 一层查找通过寻找到密切接触者的概率
    #     self.discovery_rate_2 = MysqlConnect.discovery_rate_2
    #     self.cure_rate = MysqlConnect.cure_rate
    #     self.death_rate = MysqlConnect.death_rate
    #     self.throw_number = MysqlConnect.throw_number
    #     self.N = 300
    #     self.date = 80  # 天数
    #     self.Frequency = 1  # 输入每天更新个体状态的频率
    #     # 由a状态变为b状态的概率
    #     self.rate_1_to_2 = 0.1  # 潜伏者变化为无症状的概率
    #     self.rate_1_to_4 = 0.05  # 潜伏者变化为恢复者概率
    #     self.rate_2_to_3 = 0.1  # 无症状变成感染者
    #     self.rate_2_to_4 = 0.05  # 无症状变成恢复者
    #     self.contact_effective_time = 14  # 有效接触时间
    #     self.date = 0

    '''
        函数输入：城市空位序号列，每天状态改变频数
        函数功能：清空各种状态（将所有个体状态置为0，），初始城市空位，状态改变频数增加后参数的变更，投放潜伏者
    '''

    def begin(self, empty_list, Frequency):
        # 设置参数
        self.get_parameter_txt()
        # 初始存储数组
        self.isolation_state = numpy.zeros(self.N)
        self.person = numpy.zeros(self.N)
        self.isolation_duration = numpy.zeros(self.N)  # isolation_duration隔离时长
        self.virus_Latency_duration = numpy.zeros(self.N)  # 病毒潜伏时长
        self.person_Fixed_latent_period = numpy.zeros(self.N)
        self.treatment_time = numpy.zeros(self.N)
        self.contact_effective_countdown = numpy.zeros(self.N)
        del self.record_neighbor_state[:]
        # 参数变更
        self.Frequency = int(Frequency)
        self.gt = self.gt * self.Frequency
        self.contact_effective_time = self.contact_effective_time * self.Frequency
        my_list = copy.deepcopy(self.detections_data)
        self.detections_data = [i * self.Frequency for i in my_list]  # 隔离中检测固定天数的变成检测固定次数
        # 将未在城市中的易感者设为空位
        for i in empty_list:
            this_one = i
            self.person[this_one] = -1
            self.isolation_state[this_one] = -1
            # print(this_one)

        # 投放潜伏个体
        self.throw_in_latency()


    '''
        
    '''
    # 投放病毒潜伏者
    def throw_in_latency(self):
        i = 0
        while i < self.throw_number:
            this_one = random.randint(0, self.N)
            if self.person[this_one] == 0:
                self.person[this_one] = 1
                self.virus_Latency_duration[this_one] = 1
                self.person_Fixed_latent_period[this_one] = self.get_person_Fixed_latent_period()
                print("person_Fixed_latent_period:",this_one , self.person_Fixed_latent_period[this_one])
                print("投放潜伏个体的患者：", this_one)
                self.throw_num.append(this_one)
                i = i + 1

            else:
                pass


        # print("投放潜伏个体的患者：", throw_num)
        # print("投放潜伏个体后的个体状态为：", self.person)

    '''
        函数输入：个体序列，接触网络，查找概率，是否查找已经隔了的密切接触者
        输出：输入个体序列的密切接触者序列
    '''
    # 寻找密切接触者函数
    def find_neighbors(self, find_rate, matrix, id, is_state='Y or N'):
        # 寻找密切接触者
        neighbor_number = []
        # 找到确诊者没有被确诊或者隔离的邻居
        lm = matrix[id]   # 一维矩阵
        # print(id, "的接触情况是", lm)
        for item in range(0, self.N):
            # 如果需要找的邻居包含有隔离个体（如计算易感风险时）
            if is_state == 'Y':
                # self.isolation_state[item] == 0  即使当前被隔离，仍然需要考虑隔离前的接触状态，应当将被隔离个体接触活动由此开始停止
                # if lm[item] > 0 and self.isolation_state[item] == 0:
                if lm[item] > 0:
                    a = random.uniform(0, 1)
                    # print(find_rate)
                    if a < find_rate:
                        neighbor_number.append(item)

            # 如果需要找到邻居不包含隔离个体（如通过确诊者隔离风险个体）
            else:
                if lm[item] > 0 and self.isolation_state[item] == 0:
                    a = random.uniform(0, 1)
                    # print(find_rate)
                    if a < find_rate:
                        neighbor_number.append(item)

        return neighbor_number

    '''
    def people_out(self):
        # 迁出人群只在未隔离易感中选择
        people_out = []
        n = 10
        out_list0 = random.sample(self.person_state_0, n)  # 从易感人群抽取迁出人数组
        for i in range(0, n):
            this_one = out_list0[i]  # 获取该个体的id
            self.person[this_one] = -1  # 设为未在城市状态
            self.isolation_state[this_one] = -1

        # print("迁出操作迁出者序号：", people_out)
        return people_out


    def people_in(self, people_in):
        # 传一个迁入数组
        # print(people_in)  # 从接触网络接收迁入个体序号
        for i in people_in:
            this_one = i
            self.person[this_one] = 0
            self.isolation_state[this_one] = 0
            # 迁入人群的状态赋值
            a = random.uniform(0, 1)
            # maigratin_hide_rate迁入潜伏率；maigratin_infect_rate迁入感染率；maigratin_asymptomatic_rate迁入无症状感染率
            b = self.maigratin_hide_rate
            c = self.maigratin_hide_rate + self.maigratin_infected_rate
            d = self.maigratin_hide_rate + self.maigratin_infected_rate + self.maigratin_asymptomatic_rate
            if a < b:
                self.person[this_one] = 1
                # print("迁入潜伏者：", this_one)

            elif a < c:
                self.person[this_one] = 2
                # print("迁入感染者：", this_one)

            elif a < d:
                self.person[this_one] = 3
                # print("迁入无症状感染者：", this_one)

        # self.judge_state(people_in)  # 迁入人群的核酸检测和隔离
'''

    '''
        函数输入：接触网络矩阵
        函数功能：利用接触网络和个体状态，找到与携带病毒个体的患者，并将状态标记为10
    '''

    # 按接触过携带病毒的个体选取易感人群
    def find_people_at_risk_of_infection(self, matrix):
        need_to_find = []
        need_to_depend = []
        p_id_10_0 = []
        p_id_10 = []
        for i in range(0, self.N):
            if self.person[i] == 10:
                if self.contact_effective_countdown[i] < self.contact_effective_time:
                    self.contact_effective_countdown[i] += 1
                    need_to_depend.append(i)
                    p_id_10.append(i)

                else:
                    self.person[i] = 0
                    p_id_10_0.append(i)

            elif 0 < self.person[i] < 4 and self.isolation_state[i] == 0:
                neighbors = self.find_neighbors(1, matrix, i, 'Y')
                need_to_find.append(i)
                # print("需要判断接触易感的携带病毒者为：", i)
                # print("该个体的状态和隔离状态为", self.person[i], self.isolation_state[i])
                # print(i, "携带病毒的的邻近是", neighbors)
                for item in neighbors:
                    if self.person[item] == 0:
                        self.person[item] = 10
                        # 由于考虑到会有不同的另一个个体重新接触了该个体。
                        self.contact_effective_countdown[item] = matrix[i][item]  #(C_time 从接触网络来)
                        need_to_depend.append(item)
                        p_id_10.append(i)
                    elif self.person[item] == 10:
                        if self.contact_effective_countdown[item] > matrix[i][item]:
                            self.contact_effective_countdown[item] = matrix[i][item]
                            p_id_10.append(i)
                        else:
                            pass

                    else:
                        pass

        # 返回当天标记的个体序列
        return need_to_depend
        # print("需要寻找其邻居的携带病毒的个体为：", need_to_find)
        # print("需要检查的易感个体有", need_to_depend)

    '''
        函数功能：等新当前不可以接触他人（隔离者、确诊者、死亡个体）的个体序列
    '''
    def find_not_contract_people(self):
        del self.isolation_people[:]
        for i in range(0, self.N):
            if self.isolation_state[i] > 0:
                self.isolation_people.append(i)

            else:
                pass

    '''
        函数输入：当前时间（第几天或者第几次的状态变化），接触网络
        函数功能： 更新当前天数；
                  更新对有感染风险易感者的标记；
                  克隆主程序需要用到的旧（前一天）状态数列。
                  更新不可接触（隔离者、确诊者、死亡个体）个体序列
    '''

    def update(self, t, matrix):
        #
        self.date = t
        # 确诊概率随天数增加，前十五天低，后面随天数增加
        self.find_people_at_risk_of_infection(matrix)
        self.find_not_contract_people()
        # 克隆操作，深拷贝
        self.cloning_person = copy.deepcopy(self.person)
        self.cloning_isolation_state = copy.deepcopy(self.isolation_state)
        self.cloning_treatment_time = copy.deepcopy(self.treatment_time)

    # 未隔离个体处理

    '''
         函数输入：接触网络矩阵，当前判断个体的id序号
         函数功能：通过接触的分析个体状态情况，
                 计算当前个体感染对风险系数，
                 并对感染个体进行状态转移
     '''

    # 易感个体处理
    def un_isolation_person_0(self, matrix, id, p_id_10, p_id_10_1, list_R, list_N):
        this_one = id
        p_id_10.append(this_one)
        neighbor_number = self.find_neighbors(1, matrix, id, 'Y')  # 找到接触邻居
        susceptible_risk = self.un_isolation_susceptible_risk(neighbor_number)  # 计算风险系数
        list_N.append(len(neighbor_number))
        list_R.append(susceptible_risk)
        if random.uniform(0, 1) < susceptible_risk:
            # 变为无症状无感染（潜伏）
            self.person[this_one] = 1
            self.virus_Latency_duration[this_one] = 0
            self.person_Fixed_latent_period[this_one] = self.get_person_Fixed_latent_period()
            p_id_10_1.append(this_one)

        return susceptible_risk

    # 潜伏个体处理
    '''
         函数输入：当前判断个体的id序号
         函数功能：判断是否在潜伏期内，
                   若不在则进行状态转移
     '''

    def un_isolation_person_1(self, id, p_id_1, p_id_1_2, p_id_1_3, p_id_1_4):
        this_one = id
        self.virus_Latency_duration[this_one] += 1
        # 如果超过该个体的固定潜伏期时长，该个体状态就变成感染
        if self.virus_Latency_duration[this_one] > self.person_Fixed_latent_period[this_one]:
            print("virus_Latency_duration", this_one,self.virus_Latency_duration[this_one])
            print("person_Fixed_latent_period",this_one,self.person_Fixed_latent_period[this_one])
            # 改变个体状态 , 有症状可感染状态 ，无症状有感染，恢复状态（三种状态的产生比例rate_1_to_3 > rate_1_to_2 > rate_1_to_4）
            p_id_1.append(this_one)
            a = random.uniform(1, 0)
            if a < self.rate_1_to_4:
                self.person[this_one] = 4
                p_id_1_4.append(this_one)

            elif a < self.rate_1_to_2 + self.rate_1_to_4:
                self.person[this_one] = 2
                self.asymptomatic_fix_time[this_one] = self.get_asymptomatic_fix_time()
                self.asymptomatic_time[this_one] = 0
                p_id_1_2.append(this_one)

            # 设置有症状感染者
            elif a < self.rate_1_to_2 + self.rate_1_to_3 + self.rate_1_to_4:
                self.person[this_one] = 3
                self.symptomatic_fix_time[this_one] = self.get_recovery_time()
                self.symptomatic_time[this_one] = 0
                p_id_1_3.append(this_one)
            else:
                pass

        else:
            pass

    # 无症状个体处理
    '''
         函数输入：当前判断个体的id序号
         函数功能：对于超过无症状期限的个体，按照一定比率进行状态转移
                 （注意： 无症状有感染者有可能会变成，恢复者，感染者，以及仍然保持原有状态）
    '''

    def un_isolation_person_2(self, id, p_id_2,  p_id_2_3, p_id_2_4):
        this_one = id
        self.asymptomatic_time[this_one] += 1
        if self.asymptomatic_time[this_one] >= self.asymptomatic_fix_time[this_one]:
            print("asymptomatic_time", this_one, self.asymptomatic_time[this_one])
            print("asymptomatic_fix_time",this_one,self.asymptomatic_fix_time[this_one])
            p_id_2.append(this_one)
            a = random.uniform(0, 1)
            # 无症状有感染者有可能会变成，恢复者，感染者，以及仍然保持原有状态（无症状感染者）不变。（比例为rate_2_to_4 < rate_2_to_3 < rate_remain
            if a < self.rate_2_to_4:
                self.person[this_one] = 4
                p_id_2_4.append(this_one)
            elif a < self.rate_2_to_3 + self.rate_2_to_4:
                self.person[this_one] = 3
                self.symptomatic_fix_time[this_one] = self.get_recovery_time()
                self.symptomatic_time[this_one] = 0
                p_id_2_3.append(this_one)
            else:
                pass

        else:
            pass

    # 有症状个体处理
    '''
         函数输入：当前判断个体的id序号
         函数功能：按照确诊率，对感染个体确诊
    '''

    def un_isolation_person_3(self, id, p_id_3, p_id_3_5, is_id_0_2):
        this_one = id
        self.symptomatic_time[this_one] += 1
        # 确诊率为b, 在 update（）函数里更新与当前天数有关，在turnp里转换（隔离未隔离状态下的确诊率有所不同）
        # print("感染状态转移中，确诊率", self.b)
        if random.random() < self.b:
            # 显性个体状态改变为确诊，个体带病状态不变
            self.isolation_state[this_one] = 2
            self.treatment_time[id] = 1
            self.recovery_time[this_one] = self.get_recovery_time()
            is_id_0_2.append(this_one)

        elif self.symptomatic_fix_time[this_one] < self.symptomatic_time[this_one]:
            p_id_3.append(this_one)
            if random.random() < self.rate_3_to_5:
                self.person[this_one] = 5
                self.isolation_state[this_one] = 3
                p_id_3_5.append(this_one)

            else:
                pass

        else:
            pass


    '''
         函数输入：当前需要检测存有id序号的数组
         函数功能：携带病毒个体按照检测率确诊，
                   未携带病毒个体进行隔离或继续隔离
    '''

    def judge_state(self, person_need_judge, is_x_to_2):
        for j in person_need_judge:
            this_two = j
            # print(this_two)
            # 如果密切接触者是携带病毒者，按照检测确诊率被确诊
            if 0 < self.person[this_two] < 4:
                if random.uniform(0, 1) < self.get_detection_accuracy():
                    self.isolation_state[this_two] = 2
                    self.isolation_duration[this_two] = 0
                    self.treatment_time[this_two] = 1
                    self.recovery_time[this_two] = self.get_recovery_time()
                    is_x_to_2.append(this_two)

                else:
                    pass

            # 否则将该个体进行隔离,或者继续隔离
            elif self.isolation_state[this_two] == 0:
                self.isolation_state[this_two] = 1
                # 隔离时间为一天
                self.isolation_duration[this_two] += 1

    # 隔离个体处理
    '''
        函数输入：当前判断个体的id序号
        函数功能：对于特殊隔离时间进行核酸检测
                  对于隔离期内的个体进行检测、状态变化，
                  超过隔离期的个体释放
    '''

    def isolation_person(self, id, is_1, is_id_1_0, is_id_1_2):
        this_one = id
        is_1.append(this_one)
        is_p_1 = []
        is_p_2 = []
        is_p_3 = []
        is_p_1_2 = []
        is_p_1_3 = []
        is_p_1_4 = []
        is_p_2_3 = []
        is_p_2_4 = []
        is_p_3_5 = []
        is_is_1_2 = []
        # print("当前隔离判断的个体为", this_one, "隔离期为", self.isolation_duration[this_one])
        # 在特殊隔离期时，进行核酸检测
        if self.isolation_duration[this_one] > self.gt:
            self.isolation_state[this_one] = 0
            self.isolation_duration[this_one] = 0
            is_id_1_0.append(this_one)

        # 在隔离期内的继续隔离，并且更新状态
        else:
            self.isolation_duration[this_one] += 1
            # 潜伏个体处理
            if self.person[this_one] == 1:
                self.un_isolation_person_1(this_one, is_p_1, is_p_1_2, is_p_1_3, is_p_1_4)

            elif self.person[this_one] == 2:
                self.un_isolation_person_2(this_one, is_p_2,  is_p_2_3, is_p_2_4)

            # 感染个体按一定比例确诊
            elif self.person[this_one] == 3:
                self.un_isolation_person_3(this_one, is_p_3,  is_p_3_5, is_is_1_2)
                is_id_1_2.extend(is_is_1_2)

        # 超过隔离期释放
        if self.isolation_duration[this_one] in self.detections_data:
            l = [this_one]
            self.judge_state(l, is_is_1_2)
            is_id_1_2.extend(is_is_1_2)

        else:
            pass


    # 当日确诊者（新增确诊者）的处理（隔离密切接触者）
    '''
        函数输入：当前判断个体的id序号，接触网络矩阵
        函数功能：对于新增个体获取治愈时间，
                 通过隔离比率寻找密切接触者并进行一层和二层的judge（检测和隔离）
    '''

    def new_diagnosis(self, matrix, id, is_2_new, is_t_0_1, is_id_0_2, list_NN):
        this_one = id
        is_2_new.append(this_one)
        is_is_2_find_2 = []
        # 进入治疗初始
        self.treatment_time[this_one] += 1
        # 寻找密切接触者
        neighbor_all_number = self.find_neighbors(1, matrix, id, 'N')
        neighbor_number = random.sample(neighbor_all_number, int(self.discovery_rate_1*len(neighbor_all_number)))
        neighbor.neighbor_.append(neighbor_all_number)
        list_NN.append(len(neighbor_number))
        self.judge_state(neighbor_number, is_is_2_find_2)

        # 二层隔离
        # 用neighbor_number2存储接触者的邻居，找到其没有被确诊或者隔离的邻居
        for i in neighbor_number:
            neighbor_all_number2 = self.find_neighbors(1, matrix, i, 'N')
            neighbor_number2 = random.sample(neighbor_all_number, int(self.discovery_rate_2*len(neighbor_all_number2)))
            # 按比例把没隔离的隔离
            self.judge_state(neighbor_number2, is_is_2_find_2)
            is_id_0_2.extend(is_is_2_find_2)

    '''
        函数输入：当前判断个体的id序号
        函数功能：对于确诊的个体的治疗，超出治疗时长后按照治愈率恢复，否则死亡
    '''

    def recovery_and_death(self, id, is_2_old, is_id_2_3, is_id_2_0):
        this_one = id
        a = random.random()
        # 个体治疗时间到达治愈时间，按照治愈率对该个体进行治愈
        if self.treatment_time[this_one] < self.recovery_time[this_one]:
            self.treatment_time[this_one] += 1

        else:
            is_2_old.append(this_one)
            if a < self.get_cure_rate():
                self.person[this_one] = 4
                self.isolation_state[this_one] = 0
                is_id_2_0.append(this_one)

            else:
                self.person[this_one] = 5
                self.isolation_state[this_one] = 3
                is_id_2_3.append(this_one)

    '''
        函数输入：当前判断个体的id序号
        函数功能：进行判断个体的隔离状态后，确定相应的确诊率和无症状比率
                （由于隔离和未隔离的确诊率以及无症状感染者感染比率是不一样的）
    '''

    def transfer(self, id):
        this_one = id
        if self.isolation_state[this_one] == 0:
            self.b = self.un_isolation_diagnosis_rate()
            # self.rate_1_to_2 = self.P1 / self.Frequency
        else:
            self.b = self.isolation_diagnosis_rate()
            # self.rate_1_to_2 = self.P2 / self.Frequency

    '''
        函数输入：当前判断个体的id序列
        函数功能：对这串序列中携带病毒的不同状态下个体进行计数，利用这些携带病毒个体的数量计算接触了该序列的个体感染风险
    '''

    def un_isolation_susceptible_risk(self, neighbor_number):
        # print(self.person_state_0[find_people_0[i]], "的邻居为", neighbor_number)
        # 邻居中感染数量
        emp3 = 0
        # 邻居中无症状感染者的数量
        emp2 = 0
        for i1 in neighbor_number:
            # 邻居中感染且没被隔离的
            if self.person[i1] == 3 and self.isolation_state[i1] == 0:
                emp3 = emp3 + 1

            # 邻居中无症状感染且没被隔离的
            elif self.person[i1] == 2 and self.isolation_state[i1] == 0:
                emp2 = emp2 + 1

            else:
                pass

        del neighbor_number[:]
        infection_rate = self.calculate_infection_rate(emp2, emp3)
        return infection_rate

    '''
            函数返回:infection_rate
            函数输入
                emp1:接触感染者的个数
                emp2：接触潜伏者的个数
                emp3：接触无症状感染者的个数
    '''

    def calculate_infection_rate(self, emp2, emp3):
        infection_rate = (1 - math.exp(-(emp3 * self.beta + emp2 * self.beta * self.theta))) / self.Frequency
        return infection_rate

    '''
        函数返回:得到计算确诊率
        函数输入
            day：当前所在的天数
    '''

    def un_isolation_diagnosis_rate(self):
        self.delta = self.delta1

        if self.date < 15:
            self.delta = self.delta1
        else:
            self.delta = ((self.delta - self.delta2) * numpy.math.exp(-self.r * self.date) + self.delta2)

        un_isolation_diagnosis_rate = float(1 - math.exp(-self.delta)) / self.Frequency
        # un_isolation_diagnosis_rate = 0
        return un_isolation_diagnosis_rate

    '''
        函数返回:隔离感染个体确诊率
    '''

    def isolation_diagnosis_rate(self):
        isolation_diagnosis_rate = float(1 - math.exp(-self.delta2)) / self.Frequency
        return isolation_diagnosis_rate

    '''
        函数返回：核酸检测确诊率
    '''

    def get_detection_accuracy(self):
        return self.detection_accuracy / self.Frequency

    '''
        函数返回:固定潜伏时长
    '''

    def get_person_Fixed_latent_period(self):
        fixed_latent_period = 0
        while fixed_latent_period < 2 or 15 < fixed_latent_period:
            fixed_latent_period = int(numpy.random.mtrand.gamma(3.07, 2.35)) * self.Frequency

        return fixed_latent_period

    '''
        函数返回:无症状状态者固定时长
    '''

    def get_asymptomatic_fix_time(self):
        a = 0
        while a < 10 or 20 < a:
            a = int(numpy.random.poisson(14, 1) * self.Frequency)

        return a

    '''
        函数返回:治疗时长
    '''

    def get_recovery_time(self):
        a = 0
        while a < 10 or 30 < a:
            a = int(numpy.random.poisson(20, 1) * self.Frequency)

        return a

    '''
            函数返回:治愈率
    '''

    def get_cure_rate(self):
        return self.cure_rate / self.Frequency

    '''
            函数返回:死亡率
    '''

    def get_death_rate(self):
        self.death_rate = self.death_rate / self.Frequency
        return self.death_rate